import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class SmsCodeWidget extends StatefulWidget {
  final bool autoFocus;
  final double? height;
  final int length;
  final double borderRadius;
  final double fontSize;
  final TextInputType inputType;
  final Color fontColor;
  final Color backgroundColor;
  final Color borderColor;
  final double space;
  final bool obscureText;
  final Function(String)? onResultListener;

  const SmsCodeWidget(
      {Key? key,
      this.height,
      this.length = 4,
      this.backgroundColor = Colors.white,
      this.borderColor = const Color(0xffD9D9DA),
      this.fontColor = const Color(0xff262627),
      required this.space,
      this.borderRadius = 4,
      this.fontSize = 15,
      this.obscureText = false,
      this.inputType = TextInputType.number,
      this.autoFocus = true,
      this.onResultListener})
      : super(key: key);

  @override
  _SmsCodeWidgetState createState() => _SmsCodeWidgetState();
}

class _SmsCodeWidgetState extends State<SmsCodeWidget> with WidgetsBindingObserver
    implements AutofillClient, TextInputClient {
  AutofillGroupState? _currentAutoFill;
  final GlobalKey key = GlobalKey();
  OverlayEntry? entity;
  @override
  void initState() {
    super.initState();
    initTimer();
    focusNode = FocusNode(onKey: ssssss);
    WidgetsBinding.instance.addObserver(this);
    focusNode.addListener(() {
      if (!focusNode.hasFocus) {
        timer?.cancel();
        if (_hasInputConnection) _textInputConnection?.close();
      } else {
        initTimer();
        checkClipboard();
      }
    });
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    if(state==AppLifecycleState.resumed){
      checkClipboard();
      initTimer();
    }else if(state==AppLifecycleState.paused){
      timer?.cancel();
    }

  }

  void checkClipboard() async {
    final result = await Clipboard.getData(Clipboard.kTextPlain);
    final text = result?.text ?? "";
    if (text.length == widget.length) {
      final context = key.currentContext;
      final renderBox = ((context as Element).renderObject as RenderBox);
      final offset = renderBox.localToGlobal(Offset.zero);
      final size = renderBox.size;
      entity?.remove();
      entity=null;
      entity = OverlayEntry(builder: (ctx) {
        return Container(
          padding: EdgeInsets.only(
              left: offset.dx, top: offset.dy + size.height - 10),
          alignment: Alignment.topLeft,
          child: GestureDetector(
            onTap: (){
              entity?.remove();
              entity=null;
              value= value.copyWith(
                  text: text, selection: TextSelection(baseOffset: text.length, extentOffset: text.length));
              _textInputConnection?.setEditingState(value);

              focusNode.unfocus();
              _textInputConnection?.close();
              widget.onResultListener?.call(text);
              setState(() {

              });
            },
            child: Container(
              padding:
                  EdgeInsets.only(left: 16, right: 16, top: 12, bottom: 12),
              decoration: BoxDecoration(
                boxShadow: [
                  BoxShadow(
                      color: Colors.black.withOpacity(0.08),
                      offset: Offset(0, 6),
                      blurRadius: 16),
                  BoxShadow(
                      color: Colors.black.withOpacity(0.05),
                      offset: Offset(0, 9),
                      blurRadius: 28),
                  BoxShadow(
                      color: Colors.black.withOpacity(0.03),
                      offset: Offset(0, 12),
                      blurRadius: 48),
                ],
                color: Colors.white,
                borderRadius: BorderRadius.circular(10),
                border: Border.all(color: Color(0xffE3E3E3)),
              ),
              child: Text(
                text,
                style: TextStyle(
                    inherit: false, color: Color(0xff262267), fontSize: 16),
              ),
            ),
          ),
        );
      });

      Overlay.of(context)?.insert(entity!);
    }
  }

  bool isLine = true;
  Timer? timer;

  initTimer() {
    timer?.cancel();
    isLine = true;
    timer = Timer.periodic(Duration(milliseconds: 700), (timer) {
      isLine = !isLine;
      setState(() {});
    });
  }

  dispose() {
    super.dispose();
    timer?.cancel();

    entity?.remove();
    entity=null;
    WidgetsBinding.instance.removeObserver(this);
    // _textInputConnection.close();
  }

  bool isFirst = true;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    node();
    if (widget.autoFocus && isFirst) {
      isFirst = false;
      _openInputConnect();
    }
  }

  void node() {
    final autoFill = AutofillGroup.of(context);
    if (_currentAutoFill != autoFill) {
      _currentAutoFill?.unregister(autofillId);
      _currentAutoFill = autoFill;
      autoFill?.register(this);
    }
  }

  @override
  Widget build(BuildContext context) {
    // node();
    return GestureDetector(
        onTap: () {
          checkClipboard();
          _openInputConnect();
        },
        child: SizedBox(
          height: widget.height,
          key: key,
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: _buildContent(),
          ),
        ));
  }

  List<Widget> _buildContent() {
    final list = <Widget>[];
    final text = value.text;
    for (int i = 0; i < widget.length; i++) {
      if (i != 0)
        list.add(SizedBox(
          width: widget.space,
        ));
      list.add(_buildItem(text.length > i ? text[i] : '', i == text.length));
    }
    return list;
  }

  Widget _buildItem(String value, bool isSelect) {
    return Container(
      width: widget.height,
      height: widget.height,
      decoration: BoxDecoration(
          color: widget.backgroundColor,
          border: Border.all(color: widget.borderColor),
          borderRadius: BorderRadius.circular(widget.borderRadius)),
      child: Center(
        child: isSelect
            ? LayoutBuilder(builder: (context, con) {
                return Container(
                  width: 2,
                  height: con.maxHeight * 0.6,
                  color: isLine ? Color(0xff007aff) : widget.backgroundColor,
                );
              })
            : Text(
                value,
                style: TextStyle(inherit: false,
                    fontSize: widget.fontSize, color: widget.fontColor),
              ),
      ),
    );
  }

  TextInputConnection? _textInputConnection;

  bool get _hasInputConnection => _textInputConnection?.attached ?? false;
  TextEditingValue value = TextEditingValue();

  @override
  String get autofillId => "sms_$hashCode";
  late FocusNode focusNode;

  void _openInputConnect() {
    if (!_hasInputConnection) {
      _textInputConnection = _currentAutoFill != null
          ? _currentAutoFill?.attach(this, textInputConfiguration)
          : TextInput.attach(this, textInputConfiguration);
      _textInputConnection?.show();
      _textInputConnection?.requestAutofill();
      _textInputConnection?.setStyle(
          fontSize: widget.fontSize,
          fontWeight: FontWeight.normal,
          textDirection: TextDirection.ltr,
          textAlign: TextAlign.left,
          fontFamily: '');

      _textInputConnection?.setEditingState(value);
    } else {
      _textInputConnection?.show();
    }
    // focusNode=FocusNode();
    FocusScope.of(context).requestFocus(focusNode);
    // FocusManager.instance.rootScope.autofocus(node)

    final key = focusNode.onKey;
  }

  KeyEventResult ssssss(FocusNode s, RawKeyEvent s1) {
    if (s1 is RawKeyUpEvent && s1.logicalKey == LogicalKeyboardKey.backspace) {
      final text = value.text;

      if(text.isEmpty) return KeyEventResult.handled;
      final offset = value.selection;
      final newOffset = TextSelection(
          baseOffset: offset.baseOffset - 1,
          extentOffset: offset.extentOffset - 1);
      final newValue = value.copyWith(
          text: text.substring(0, text.length - 1), selection: newOffset);
      _textInputConnection?.setEditingState(newValue);
      value = newValue;
      initTimer();

      entity?.remove();
      entity=null;
      setState(() {});
    }
    return KeyEventResult.handled;
  }

  @override
  TextInputConfiguration get textInputConfiguration => TextInputConfiguration(
        inputType: widget.inputType,
        readOnly: false,
        obscureText: widget.obscureText,
        inputAction: TextInputAction.done,
      );
  String text = "";

  @override
  void updateEditingValue(TextEditingValue newEditingValue) {
    // ToastUtils.show(newEditingValue.text);
    if (newEditingValue.text.length > widget.length) {
      return;
    }
    value = newEditingValue;
    text = newEditingValue.text;
    if (text.length == widget.length) {
      focusNode.unfocus();
      _textInputConnection?.close();
      widget.onResultListener?.call(text);
    }

    entity?.remove();
    entity=null;
    initTimer();
    setState(() {});
  }

  @override
  void connectionClosed() {
    if (_hasInputConnection) _textInputConnection?.connectionClosedReceived();
  }

  @override
  AutofillScope get currentAutofillScope => _currentAutoFill!;

  @override
  TextEditingValue get currentTextEditingValue => value;

  @override
  void performAction(TextInputAction action) {
    print("pay-performAction:${action.index}");
  }

  @override
  void performPrivateCommand(String action, Map<String, dynamic> data) {
    print("pay-performPrivateCommand:${action}");
  }

  @override
  void showAutocorrectionPromptRect(int start, int end) {
    print("pay-showAutocorrectionPromptRect:${start},${end}");
  }

  @override
  void updateFloatingCursor(RawFloatingCursorPoint point) {
    print("pay-updateFloatingCursor:${point.offset}");
  }

  @override
  void autofill(TextEditingValue newEditingValue) {}

  @override
  void insertTextPlaceholder(Size size) {
  }

  @override
  void removeTextPlaceholder() {
  }

  @override
  void showToolbar() {
  }
}
